Private Function EvaluateExpr(ByVal expr As String) As Single
'文本转可直接计算的表达式

       Const PREC_NONE = 11
       Const PREC_UNARY = 10
       Const PREC_POWER = 9
       Const PREC_TIMES = 8
       Const PREC_DIV = 7
       Const PREC_INT_DIV = 6
       Const PREC_MOD = 5
       Const PREC_PLUS = 4
       Dim is_unary   As Boolean
       Dim next_unary   As Boolean
       Dim parens   As Integer
       Dim pos   As Integer
       Dim expr_len   As Integer
       Dim ch   As String
       Dim lexpr   As String
       Dim rexpr   As String
       Dim value   As String
       Dim status   As Long
       Dim best_pos   As Integer
       Dim best_prec   As Integer
       '  Remove  leading  and  trailing  blanks.
       expr = Trim$(expr)
       expr_len = Len(expr)
       If expr_len = 0 Then Exit Function
       '  If  we  find  +  or  -  now,  it  is  a  unary  operator.
       is_unary = True
       '  So  far  we  have  nothing.
       best_prec = PREC_NONE
       '  Find  the  operator  with  the  lowest  precedence.
       '  Look  for  places  where  there  are  no  open
       '  parentheses.
       For pos = 1 To expr_len
               '  Examine  the  next  character.
               ch = Mid$(expr, pos, 1)
               '  Assume  we  will  not  find  an  operator.  In
               '  that  case  the  next  operator  will  not
               '  be  unary.
               next_unary = False
               If ch = "  " Then
                       '  Just  skip  spaces.
                       next_unary = is_unary
               ElseIf ch = "(" Then
                       '  Increase  the  open  parentheses  count.
                       parens = parens + 1
                       '  An  operator  after  "("  is  unary.
                       next_unary = True
               ElseIf ch = ")" Then
                       '  Decrease  the  open  parentheses  count.
                       parens = parens - 1
                       '  An  operator  after  ")"  is  not  unary.
                       next_unary = False
                       '  If  parens  <  0,  too  many  ')'s.
                       If parens < 0 Then
                               Err.Raise vbObjectError + 1001, _
                                       "EvaluateExpr", _
                                       "Too  many  )s  in  '" & _
                                       expr & "'"
                       End If
               ElseIf parens = 0 Then
                       '  See  if  this  is  an  operator.
                       If ch = "^" Or ch = "*" Or _
                             ch = "/" Or ch = "/" Or _
                             ch = "%" Or ch = "+" Or _
                             ch = "-" _
                       Then
                               '  An  operator  after  an  operator
                               '  is  unary.
                               next_unary = True
                                 
                               Select Case ch
                                       Case "^"
                                               If best_prec >= PREC_POWER Then
                                                       best_prec = PREC_POWER
                                                       best_pos = pos
                                               End If
                                         
                                       Case "*", "/"
                                               If best_prec >= PREC_TIMES Then
                                                       best_prec = PREC_TIMES
                                                       best_pos = pos
                                               End If
                                         
                                       Case "/"
                                               If best_prec >= PREC_INT_DIV Then
                                                       best_prec = PREC_INT_DIV
                                                       best_pos = pos
                                               End If
                                         
                                       Case "%"
                                               If best_prec >= PREC_MOD Then
                                                       best_prec = PREC_MOD
                                                       best_pos = pos
                                               End If
                                         
                                       Case "+", "-"
                                               '  Ignore  unary  operators
                                               '  for  now.
                                               If (Not is_unary) And _
                                                       best_prec >= PREC_PLUS _
                                               Then
                                                       best_prec = PREC_PLUS
                                                       best_pos = pos
                                               End If
                               End Select
                       End If
               End If
               is_unary = next_unary
       Next pos
         
       '  If  the  parentheses  count  is  not  zero,
       '  there's  a  ')'  missing.
       If parens <> 0 Then
               Err.Raise vbObjectError + 1002, _
                       "EvaluateExpr", "Missing  )  in  '" & _
                       expr & "'"
       End If
         
       '  Hopefully  we  have  the  operator.
       If best_prec < PREC_NONE Then
               lexpr = Left$(expr, best_pos - 1)
               rexpr = Right$(expr, expr_len - best_pos)
               Select Case Mid$(expr, best_pos, 1)
                       Case "^"
                               EvaluateExpr = _
                                       EvaluateExpr(lexpr) ^ _
                                       EvaluateExpr(rexpr)
                       Case "*"
                               EvaluateExpr = _
                                       EvaluateExpr(lexpr) * _
                                       EvaluateExpr(rexpr)
                       Case "/"
                               EvaluateExpr = _
                                       EvaluateExpr(lexpr) / _
                                       EvaluateExpr(rexpr)
                       Case "/"
                               EvaluateExpr = _
                                       EvaluateExpr(lexpr) / _
                                       EvaluateExpr(rexpr)
                       Case "%"
                               EvaluateExpr = _
                                       EvaluateExpr(lexpr) Mod _
                                       EvaluateExpr(rexpr)
                       Case "+"
                               EvaluateExpr = _
                                       EvaluateExpr(lexpr) + _
                                       EvaluateExpr(rexpr)
                       Case "-"
                               EvaluateExpr = _
                                       EvaluateExpr(lexpr) - _
                                       EvaluateExpr(rexpr)
               End Select
               Exit Function
       End If
         
       '  If  we  do  not  yet  have  an  operator,  there
       '  are  several  possibilities:
       '
       '  1.  expr  is  (expr2)  for  some  expr2.
       '  2.  expr  is  -expr2  or  +expr2  for  some  expr2.
       '  3.  expr  is  Fun(expr2)  for  a  function  Fun.
       '  4.  expr  is  a  primitive.
       '  5.  It's  a  literal  like  "3.14159".
         
       '  Look  for  (expr2).
       If Left$(expr, 1) = "(" And Right$(expr, 1) = ")" Then
               '  Remove  the  parentheses.
               EvaluateExpr = EvaluateExpr(Mid$(expr, 2, expr_len - 2))
               Exit Function
       End If
                 
       '  Look  for  -expr2.
       If Left$(expr, 1) = "-" Then
               EvaluateExpr = -EvaluateExpr( _
                       Right$(expr, expr_len - 1))
               Exit Function
       End If
         
       '  Look  for  +expr2.
       If Left$(expr, 1) = "+" Then
               EvaluateExpr = EvaluateExpr( _
                       Right$(expr, expr_len - 1))
               Exit Function
       End If
         
       '  Look  for  Fun(expr2).
       If expr_len > 5 And Right$(expr, 1) = ")" Then
               lexpr = LCase$(Left$(expr, 4))
               rexpr = Mid$(expr, 5, expr_len - 5)
               Select Case lexpr
                       Case "sin("
                               EvaluateExpr = Sin(EvaluateExpr(rexpr))
                               Exit Function
                       Case "cos("
                               EvaluateExpr = Cos(EvaluateExpr(rexpr))
                               Exit Function
                       Case "tan("
                               EvaluateExpr = Tan(EvaluateExpr(rexpr))
                               Exit Function
                       Case "sqr("
                               EvaluateExpr = Sqr(EvaluateExpr(rexpr))
                               Exit Function
               End Select
       End If
         
       On Error Resume Next
       EvaluateExpr = CSng(expr)
       status = Err.Number
       On Error GoTo 0
       If status <> 0 Then
               Err.Raise status, _
                       "EvaluateExpr", _
                       "Error  evaluating  '" & expr & _
                       "'  as  a  constant."
       End If
End Function
